home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / mac-emacs-src / emulate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-17  |  20.6 KB  |  893 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. /* Throughout this file we save and restore ports around calls to set them.  This
  12.    is because we allow use of SetPort from lisp, and we must make sure this
  13.    notion of current port doesn't change.  A bad case would be code like:
  14.  
  15.    (SetPort gp)
  16.    ... ;;; other lisp code
  17.    (LineTo x y)
  18.  
  19.    where the code between the SetPort and the LineTo invokes garbage collection,
  20.    resulting in the familiar message "Garbage collection...done", the display of
  21.    which requires changes in the current port.  We better restore it.
  22.  */
  23.  
  24. #if defined(THINK_C)
  25. #include <MacHeaders>
  26. #else
  27. #include <Types.h>
  28. #include <Memory.h>
  29. #include <Quickdraw.h>
  30. #include <Windows.h>
  31. #include <Fonts.h>
  32. #include <ToolUtils.h>
  33. #endif
  34.  
  35. #include <Palettes.h>
  36. #include <GestaltEqu.h>
  37. #include "stdio.h"
  38. #include "signal.h"
  39. #include "config.h"
  40. #include "lisp.h"
  41. #include "termhooks.h"
  42. #include "termchar.h"
  43.  
  44. enum {
  45.     plt_white,
  46.     plt_black,
  47.     plt_grey,
  48.     plt_back,
  49.     plt_frame,
  50.     plt_text,
  51.     plt_status,
  52.     plt_status_text,
  53.     plt_cursor,
  54.     plt_cursor_text,
  55.     plt_size
  56. };
  57.  
  58. static struct {
  59.     WindowRecord wr0;
  60.     WindowPtr wp;
  61.     WCTabHandle ctab5_color,ctab5_bw;
  62.     FontInfo fi;
  63.     short lineHeight;
  64. #define CONSOLE(X,Y) console.backup[console.cols * (Y) + (X)]
  65.     char *backup,*reverse;
  66.     short cx,cy,rows,cols;
  67. } console;
  68. #define LEFT_MARGIN 4
  69. #define TOP_MARGIN    2
  70. static int flexlines;
  71. static char in_emacs_update;
  72. static Rect huge = { -32767,-32767,32767,32767 };
  73. static char have_CQD;
  74. static char window_depth_cache_valid;
  75. static char window_depth_cache;
  76.  
  77. static min (a,b) { return a<b ? a : b; }
  78.  
  79. static int
  80. use_color(void)
  81. {
  82.     GDHandle gd;
  83.     PaletteHandle ph;
  84.     Point origin;
  85.     GrafPtr gp;
  86.     Rect device_rect,console_rect,common;
  87.  
  88.     if (!have_CQD) return 0;
  89.  
  90.     ph = GetPalette(console.wp);
  91.     if ((**ph).pmEntries != plt_size) return 0;
  92.     
  93.     if (!window_depth_cache_valid) {
  94.         console_rect = console.wp->portRect;
  95.         origin.h = origin.v = 0;
  96.         GetPort(&gp);
  97.         SetPort(console.wp);
  98.         LocalToGlobal(&origin);
  99.         SetPort(gp);
  100.         OffsetRect(&console_rect,origin.h,origin.v);
  101.         window_depth_cache = 4;
  102.         for (gd = GetDeviceList(); gd != 0L; gd = GetNextDevice(gd)) {
  103.             device_rect = (**(**gd).gdPMap).bounds;
  104.             if (SectRect(&device_rect,&console_rect,&common))
  105.                 window_depth_cache = min((**(**gd).gdPMap).pixelSize,window_depth_cache);
  106.         }
  107.         window_depth_cache_valid = 1;
  108.     }
  109.  
  110.     return window_depth_cache >= 4;
  111. }
  112.  
  113. static void
  114. compute_position(int x,int y,int *sx,int *sy)
  115. {
  116.     *sx = LEFT_MARGIN + x * console.fi.widMax;
  117.     *sy = TOP_MARGIN + y * console.lineHeight;
  118. }
  119.  
  120. static void
  121. extract_position(int sx,int sy,int *x,int *y)
  122. {
  123.     *x = (sx - LEFT_MARGIN) / console.fi.widMax;
  124.     *y = (sy - TOP_MARGIN) / console.lineHeight;
  125. }
  126.  
  127. static void
  128. set_position(int x,int y)
  129. {
  130.     int sx,sy;
  131.     compute_position(x,y,&sx,&sy);
  132.     MoveTo(sx,sy + console.fi.ascent);
  133. }
  134.  
  135. static char cursor_state;
  136. enum { cursor_state_not_shown, cursor_state_solid, cursor_state_outline };
  137.  
  138. static void
  139. draw_cursor1(int state,int visible)
  140. {
  141.     Rect r;
  142.     int sx,sy;
  143.  
  144.     if (state == cursor_state_not_shown) return;
  145.     
  146.     compute_position(console.cx,console.cy,&sx,&sy);
  147.     SetRect(&r,sx,sy,sx + console.fi.widMax,sy + console.fi.ascent + console.fi.descent);
  148.     if (use_color()) {
  149.         if (visible) {
  150.             PmForeColor(plt_cursor);
  151.             if (state == cursor_state_outline)
  152.                 FrameRect(&r);
  153.             else
  154.                 PaintRect(&r);
  155.         }
  156.         else
  157.             EraseRect(&r);
  158.         PmForeColor(!visible || state == cursor_state_outline ? plt_text : plt_cursor_text);
  159.         MoveTo(sx,sy + console.fi.ascent);
  160.         DrawChar(CONSOLE(console.cx,console.cy));
  161.     }
  162.     else {
  163.         PenMode(patXor);
  164.         if (state == cursor_state_outline)
  165.             FrameRect(&r);
  166.         else
  167.             PaintRect(&r);
  168.         PenNormal();
  169.     }
  170. }
  171.  
  172. static void
  173. erase_cursor(void)
  174. {
  175.     draw_cursor1(cursor_state,0);
  176.     cursor_state = cursor_state_not_shown;
  177. }
  178.  
  179. static void
  180. draw_cursor(void)
  181. {
  182.     int newstate = ((WindowPeek)console.wp)->hilited ? cursor_state_solid :
  183.         cursor_state_outline;
  184.     if (newstate == cursor_state) return;
  185.     draw_cursor1(cursor_state,0);
  186.     cursor_state = newstate;
  187.     draw_cursor1(cursor_state,1);
  188. }
  189.  
  190. static void
  191. erase_text(int x1,int y1,int x2,int y2,int highlighted)
  192. {
  193.     int sx1,sx2,sy1,sy2;
  194.     Rect r;
  195.     
  196.     compute_position(x1,y1,&sx1,&sy1);
  197.     compute_position(x2,y2,&sx2,&sy2);
  198.     SetRect(&r,sx1,sy1,sx2 + console.fi.widMax,sy2 + console.fi.ascent + console.fi.descent);
  199.     if (highlighted) {
  200.         if (use_color()) PmForeColor(plt_status);
  201.         PaintRect(&r);
  202.     }
  203.     else
  204.         EraseRect(&r);
  205. }
  206.  
  207. static void
  208. my_move_cursor_hook(int y,int x)
  209. {
  210.     GrafPtr gp;
  211.  
  212.     if (!in_emacs_update) GetPort(&gp), SetPort(console.wp), erase_cursor();
  213.     console.cx = x;
  214.     console.cy = y;
  215.     if (!in_emacs_update) draw_cursor(), SetPort(gp);
  216. }
  217.  
  218. static void
  219. set_text_mode_and_color(int row)
  220. {
  221.     if (use_color())
  222.         if (console.reverse && console.reverse[row])
  223.             PmForeColor(plt_status_text);
  224.         else
  225.             PmForeColor(plt_text);
  226. }
  227.  
  228. static void
  229. my_output_chars_hook(char *s,int n)
  230. {
  231.     GrafPtr gp;
  232.     int chars_to_write = min(n,console.cols - console.cx);
  233.     
  234.     GetPort(&gp);
  235.     SetPort(console.wp);
  236.     if (!in_emacs_update) erase_cursor();
  237.     erase_text(console.cx,console.cy,
  238.         console.cx+chars_to_write-1,console.cy,
  239.                console.reverse && console.reverse[console.cy]);
  240.     set_position(console.cx,console.cy);
  241.     set_text_mode_and_color(console.cy);
  242.     DrawText(s,0,chars_to_write);
  243.     if (console.backup) memcpy(&CONSOLE(console.cx,console.cy),s,chars_to_write);
  244.     console.cx += chars_to_write;
  245.     if (!in_emacs_update) draw_cursor();
  246.     SetPort(gp);
  247. }
  248.  
  249. static void
  250. my_clear_screen_hook(void)
  251. {
  252.     GrafPtr gp;
  253.  
  254.     GetPort(&gp);
  255.     SetPort(console.wp);
  256.     erase_text(0,0,console.cols-1,console.rows,0);
  257.     cursor_state = cursor_state_not_shown;
  258.  
  259.     if (console.backup && console.reverse) {
  260.         memset(console.backup,' ',console.cols * console.rows);
  261.         memset(console.reverse,0,console.rows);
  262.     }
  263.     console.cx = console.cy = 0;
  264.     if (!in_emacs_update) draw_cursor();
  265.     SetPort(gp);
  266. }
  267.  
  268. static void
  269. my_clear_end_of_line_hook(int first_unused_hpos)
  270. {
  271.     GrafPtr gp;
  272.     int last_col = min(first_unused_hpos,console.cols) - 1;
  273.  
  274.     GetPort(&gp);
  275.     SetPort(console.wp);
  276.     if (!in_emacs_update) erase_cursor();
  277.     erase_text(console.cx,console.cy,last_col,console.cy,
  278.                console.reverse && console.reverse[console.cy]);
  279.     if (!in_emacs_update) draw_cursor();
  280.     if (console.backup) memset(&CONSOLE(console.cx,console.cy),' ',last_col - console.cx + 1);
  281.     SetPort(gp);
  282. }
  283.  
  284. static void
  285. my_ring_bell_hook(void)
  286. {
  287.     SysBeep(3);
  288. }
  289.  
  290. static void
  291. my_set_terminal_window_hook(int n)
  292. {
  293.     /*    From reading the comments of x11term.c, it sounds like lines number up
  294.         to and including flexlines are affected by scrolling operations.  From
  295.         reading the code, it looks like lines numbers up to, but not including,
  296.         flexlines are affected. */
  297.     
  298.     flexlines = (n <= 0 || n > console.rows) ? console.rows : n;
  299. }
  300.  
  301. static void
  302. my_ins_del_lines_hook(int vpos,int n)
  303. {
  304.     // vpos is the top line of the region being scrolled
  305.     // flexlines is one past the bottom of the region being scrolled
  306.     // n in the number of lines to scroll.
  307.     
  308.     Rect r;
  309.     GrafPtr gp;
  310.     RgnHandle rgn;
  311.     int sx1,sy1,sx2,sy2;
  312.     
  313.     GetPort(&gp);
  314.     SetPort(console.wp);
  315.     if (!in_emacs_update) erase_cursor();
  316.     compute_position(0,vpos,&sx1,&sy1);
  317.     compute_position(console.cols-1,flexlines-1,&sx2,&sy2);
  318.     SetRect(&r,sx1,sy1,sx2 + console.fi.widMax,sy2 + console.fi.ascent + console.fi.descent);
  319.     rgn = NewRgn();
  320.     ScrollRect(&r,0,n*console.lineHeight,rgn);
  321.     DisposeRgn(rgn);
  322.     if (!in_emacs_update) draw_cursor();
  323.     SetPort(gp);
  324.     
  325.     if (console.backup) {
  326.         if (n>0) {
  327.             memmove(&CONSOLE(0,vpos+n),&CONSOLE(0,vpos),
  328.                     (flexlines - vpos - n) * console.cols);
  329.             memset(&CONSOLE(0,vpos),' ',n * console.cols);
  330.         }
  331.         else {
  332.             n = -n;
  333.             memmove(&CONSOLE(0,vpos),&CONSOLE(0,vpos+n),
  334.                     (flexlines - vpos - n) * console.cols);
  335.             memset(&CONSOLE(0,flexlines - n),' ',n * console.cols);
  336.         }
  337.     }
  338. }
  339.  
  340. static void
  341. my_change_line_highlight_hook(int highlighted,int vpos,int first_unused_hpos)
  342. {
  343.     GrafPtr gp;
  344.     int last_col = min(first_unused_hpos,console.cols) - 1;
  345.  
  346.     GetPort(&gp);
  347.     SetPort(console.wp);
  348.     my_move_cursor_hook(vpos,0);
  349.     erase_text(0,vpos,console.cols-1,vpos,highlighted);
  350.     if (console.reverse) console.reverse[vpos] = highlighted != 0;
  351.     if (console.backup) memset(&CONSOLE(0,vpos),' ',console.cols);
  352.     SetPort(gp);
  353. }
  354.  
  355. static void
  356. my_reassert_line_highlight_hook(int highlight,int vpos)
  357. {
  358.     if (console.reverse) console.reverse[vpos] = highlight;
  359. }
  360.  
  361. static void
  362. my_update_begin(int x)
  363. {
  364.     if (!in_emacs_update) {
  365.         GrafPtr gp;
  366.         GetPort(&gp);
  367.         SetPort(console.wp);
  368.         erase_cursor();
  369.         SetPort(gp);
  370.     }
  371.     ++in_emacs_update;
  372. }
  373.  
  374. static void
  375. my_update_end(int x)
  376. {
  377.     --in_emacs_update;
  378.     if (!in_emacs_update) {
  379.         GrafPtr gp;
  380.         GetPort(&gp);
  381.         SetPort(console.wp);
  382.         draw_cursor();
  383.         SetPort(gp);
  384.     }
  385. }
  386.  
  387. static void
  388. my_calculate_costs_hook(int extra,int *costvec,int *ncostvec)
  389. {
  390.     CalcLID(0,screen_width/5,0,0,costvec,ncostvec);
  391. }
  392.  
  393. static void
  394. my_fix_screen_hook(void)
  395. {
  396.     read_events(0);
  397. }
  398.  
  399. static void
  400. reset_size(int rows,int cols)
  401. {
  402.     console.rows = rows;
  403.     console.cols = cols;
  404.     if (console.backup) DisposPtr(console.backup), console.backup = 0L;
  405.     console.backup = NewPtr(console.cols * console.rows);
  406.     if (console.reverse) DisposPtr(console.reverse), console.reverse = 0L;
  407.     console.reverse = NewPtr(console.rows);
  408.     console.cx = console.cy = 0;
  409.     if (console.backup && console.reverse) {
  410.         memset(console.backup,' ',console.cols * console.rows);
  411.         memset(console.reverse,0,console.rows);
  412.     }
  413. }
  414.  
  415. static Rect
  416. get_previous_windowsize(void)
  417. {
  418.     /* This gives a 24 by 80 window using Monaco 9, the default font. */
  419.     static Rect default_rect = { 50,4,50 + 24*11 + 2*TOP_MARGIN,
  420.                                      4 + 80*6 + 15 + 2*LEFT_MARGIN };
  421.     Rect r,**preferred_rect;
  422.     int err;
  423.     RgnHandle common_rgn,titlebar_rgn;
  424.  
  425.     err = get_preference('DATA',128,(Handle *)&preferred_rect);
  426.     if (err)
  427.         r = default_rect;
  428.     else {
  429.         r = **preferred_rect;
  430.         DisposHandle((Handle)preferred_rect);
  431.         
  432.         /* Make sure the titlebar appears somewhere on the desktop */
  433.  
  434.         common_rgn = NewRgn();
  435.         titlebar_rgn = NewRgn();
  436.         SetRectRgn(titlebar_rgn,r.left,r.top - 18,r.right,r.top);
  437.         SectRgn(titlebar_rgn,GetGrayRgn(),common_rgn);
  438.         if (EmptyRgn(common_rgn)) r = default_rect;
  439.         DisposeRgn(common_rgn);
  440.         DisposeRgn(titlebar_rgn);
  441.     }
  442.  
  443.     return r;
  444. }
  445.  
  446. static void
  447. windowsize2rowscols(long *rows,long *cols)
  448. {
  449.     *cols = (console.wp->portRect.right - 15 - 2*LEFT_MARGIN) / console.fi.widMax;
  450.     *rows = (console.wp->portRect.bottom - 2*TOP_MARGIN) / console.lineHeight;
  451. }
  452.  
  453. static void
  454. set_console_font(font,size)
  455. {
  456.     static int last_font,last_size;
  457.  
  458.     if (font == -1)
  459.         font = last_font;
  460.     else
  461.         last_font = font;
  462.     if (size == -1)
  463.         size = last_size;
  464.     else
  465.         last_size = size;
  466.     
  467.     TextFont(font);
  468.     TextSize(size);
  469.     GetFontInfo(&console.fi);
  470.     console.lineHeight = console.fi.ascent + console.fi.descent + console.fi.leading;
  471.     // The returned value from GetFontInfo is not always right.
  472.     console.fi.widMax = CharWidth('m');
  473. }
  474.  
  475. static void
  476. fixup_colors(void)
  477. {
  478.     RGBColor c;
  479.     PaletteHandle ph;
  480.     static char last_use_color = -1;
  481.  
  482.     if (!have_CQD) {
  483.         TextMode(srcXor);
  484.         return;
  485.     }
  486.  
  487.     if (last_use_color == use_color()) return;
  488.     last_use_color = use_color();
  489.  
  490.     if (use_color()) {
  491.         SetPort(console.wp);
  492.         TextMode(srcOr);
  493.         PmBackColor(plt_back);
  494.         ph = GetPalette(console.wp);
  495.         GetEntryColor(ph,plt_back,&c);
  496.         (**console.ctab5_color).ctTable[0].rgb = c;
  497.         GetEntryColor(ph,plt_frame,&c);
  498.         (**console.ctab5_color).ctTable[1].rgb = c;
  499.         SetWinColor(console.wp,(WCTabHandle)console.ctab5_color);
  500.     }
  501.     else {
  502.         SetPort(console.wp);
  503.         TextMode(srcXor);
  504.         PmForeColor(plt_black);
  505.         PmBackColor(plt_white);
  506.         SetWinColor(console.wp,(WCTabHandle)console.ctab5_bw);
  507.     }
  508. }
  509.  
  510. static void
  511. init_console(void)
  512. {
  513.     Rect r;
  514.     Handle h;
  515.     RGBColor c;
  516.     PaletteHandle ph;
  517.     char use_color_pref;
  518.     short **use_color_pref_handle;
  519.     long rows,cols,err,response,fontname,fontsize;
  520.  
  521.     err = Gestalt(gestaltQuickdrawVersion,&response);
  522.     have_CQD = (err == 0 && response >= gestalt8BitQD);
  523.     
  524.     console.wp = (WindowPtr)&console.wr0;
  525.  
  526.     if (have_CQD) {
  527.         GetNewCWindow(136,console.wp,(WindowPtr)-1);
  528.         console.ctab5_color = (WCTabHandle)GetCTable(128);
  529.         console.ctab5_bw = (WCTabHandle)GetCTable(129);
  530.         err = get_preference('DATA',133,(Handle *)&use_color_pref_handle);
  531.         use_color_pref = (err != noErr) || **use_color_pref_handle;
  532.         err = get_preference('pltt',132,(Handle *)&ph);
  533.         if (err == noErr) {
  534.             if (!use_color_pref) ResizePalette(ph,2);
  535.             else if ((**ph).pmEntries == plt_size-1) {
  536.                 // An old prefs file missing the last entry
  537.                 ResizePalette(ph,plt_size);
  538.                 GetEntryColor(ph,plt_text,&c);
  539.                 SetEntryColor(ph,plt_cursor_text,&c);
  540.             }
  541.             NSetPalette(console.wp,ph,pmAllUpdates);
  542.         }
  543.         else {
  544.             ph = GetPalette(console.wp);
  545.             if (!use_color_pref) ResizePalette(ph,2);
  546.             SetPaletteUpdates(ph,pmAllUpdates);
  547.         }
  548.     }
  549.     else
  550.         GetNewWindow(136,console.wp,(WindowPtr)-1);
  551.  
  552.     SetPort(console.wp);
  553.     err = get_preference('DATA',130,&h);
  554.     fontname = err ? monaco : **(short **)h;
  555.     err = get_preference('DATA',131,&h);
  556.     fontsize = err ? 9 : **(short **)h;
  557.     set_console_font(fontname,fontsize);
  558.  
  559.     r = get_previous_windowsize();
  560.     MoveWindow(console.wp,r.left,r.top,0);
  561.     SizeWindow(console.wp,r.right - r.left,r.bottom - r.top,0);
  562.     ShowWindow(console.wp);
  563.     r = console.wp->portRect;
  564.     r.right -= 15;
  565.     ValidRect(&r);
  566.     windowsize2rowscols(&rows,&cols);
  567.     reset_size(rows,cols);
  568. }
  569.  
  570. void
  571. apple_init_display(void)
  572. {
  573.     extern int meta_key;
  574.     
  575.     init_console();
  576.  
  577.     update_begin_hook = (int (*)())my_update_begin;
  578.     update_end_hook = (int (*)())my_update_end;
  579.     move_cursor_hook = (int (*)())my_move_cursor_hook;
  580.     raw_move_cursor_hook = (int (*)())my_move_cursor_hook;
  581.     output_chars_hook = (int (*)())my_output_chars_hook;
  582.     clear_screen_hook = (int (*)())my_clear_screen_hook;
  583.     clear_end_of_line_hook = (int (*)())my_clear_end_of_line_hook;
  584.     ring_bell_hook = (int (*)())my_ring_bell_hook;
  585.     change_line_highlight_hook = (int (*)())my_change_line_highlight_hook;
  586.     reassert_line_highlight_hook = (int (*)())my_reassert_line_highlight_hook;
  587.     ins_del_lines_hook = (int (*)())my_ins_del_lines_hook;
  588.     set_terminal_window_hook = (int (*)())my_set_terminal_window_hook;
  589.     calculate_costs_hook = (int (*)())my_calculate_costs_hook;
  590.     fix_screen_hook = (int (*)())my_fix_screen_hook;
  591.  
  592.     baud_rate = 4*9600;
  593.     fast_clear_end_of_line = 1;
  594.     dont_calculate_costs = 1;
  595.     memory_below_screen = 0;
  596.     must_write_spaces = 1; // Not true, but it seems to run faster with this on.
  597.     char_ins_del_ok = 0; // It runs faster without this feature than with it.
  598.     line_ins_del_ok = 1;
  599.     scroll_region_ok = 1;
  600.     screen_width = console.cols;
  601.     screen_height = console.rows;
  602.     meta_key = 0;
  603. }
  604.  
  605. static Rect
  606. window_rect(Lisp_Object window)
  607. {
  608.     Rect r;
  609.     int x1,y1,x2,y2;
  610.     Lisp_Object edges;
  611.  
  612.     edges = Fwindow_edges(window);
  613.     compute_position(XINT(Fcar(edges)),XINT(Fcar(Fcdr(edges))),&x1,&y1);
  614.     compute_position(XINT(Fcar(Fcdr(Fcdr(edges)))),
  615.                      XINT(Fcar(Fcdr(Fcdr(Fcdr(edges)))))-2,&x2,&y2);
  616.     y2 += console.fi.ascent + console.fi.descent;
  617.     SetRect(&r,x1,y1,x2,y2);
  618.     return r;
  619. }
  620.  
  621. static Lisp_Object
  622. get_clipboard_window(void)
  623. {
  624.     Lisp_Object clipboard_string,clipboard_buffer,clipboard_window;
  625.  
  626.     clipboard_string = build_string("*clipboard*");
  627.     clipboard_buffer = Fget_buffer(clipboard_string);
  628.     if (NULL(clipboard_buffer)) return Qnil;
  629.     clipboard_window = Fget_buffer_window(clipboard_buffer);
  630.     return clipboard_window;
  631. }
  632.  
  633. static void
  634. draw_console(void)
  635. {
  636.     int i;
  637.     RgnHandle rgn;
  638.     Rect clipboard_rect;
  639.     Lisp_Object clipboard_window;
  640.     
  641.     if (!((WindowRecord *)console.wp)->hilited) {
  642.         clipboard_window = get_clipboard_window();
  643.         if (!NULL(clipboard_window)){
  644.             clipboard_rect = window_rect(clipboard_window);
  645.             InsetRect(&clipboard_rect,0,1);
  646.             PenPat(&qd.ltGray);
  647.             // if (use_color()) PmForeColor(plt_grey);
  648.             PaintRect(&clipboard_rect);
  649.             PenNormal();
  650.  
  651.             rgn = NewRgn();
  652.             RectRgn(rgn,&clipboard_rect);
  653.             DiffRgn(console.wp->clipRgn,rgn,console.wp->clipRgn);
  654.             DisposeRgn(rgn);
  655.         }
  656.     }
  657.     
  658.     if (console.backup && console.reverse) {
  659.         for (i = 0; i<console.rows; ++i) {
  660.             if (console.reverse[i]) erase_text(0,i,console.cols-1,i,1);
  661.             set_text_mode_and_color(i);
  662.             set_position(0,i);
  663.             DrawText(&CONSOLE(0,i),0,console.cols);
  664.         }
  665.     }
  666.     
  667.     ClipRect(&huge);
  668. }
  669.  
  670. void
  671. my_DrawGrowIcon(WindowPtr w)
  672. {
  673.     Rect r = w->portRect;
  674.     r.left = r.right - 15;
  675.     ClipRect(&r);
  676.     DrawGrowIcon(w);
  677.     ClipRect(&huge);
  678. }
  679.  
  680. void
  681. fixup_clipboard(int update_contents)
  682. {
  683.     GrafPtr gp;
  684.     Rect clipboard_rect;
  685.     Lisp_Object mcc,clipboard_window;
  686.  
  687.     if (update_contents && !NULL(mcc = Fintern_soft(build_string("make-clipboard-current"),Qnil)))
  688.         pass_up_lisp_command(Fcons(mcc,Qnil));
  689.  
  690.     clipboard_window = get_clipboard_window();
  691.     if (!NULL(clipboard_window)) {
  692.         clipboard_rect = window_rect(clipboard_window);
  693.         GetPort(&gp);
  694.         SetPort(console.wp);
  695.         InvalRect(&clipboard_rect);
  696.         SetPort(gp);
  697.     }
  698. }
  699.  
  700. void
  701. console_activate(int activate)
  702. {
  703.     GrafPtr gp;
  704.  
  705.     GetPort(&gp);
  706.     SetPort(console.wp);
  707.     my_DrawGrowIcon(console.wp);
  708.     if (!in_emacs_update) draw_cursor();
  709.     SetPort(gp);
  710. }
  711.  
  712. void
  713. console_update(void)
  714. {
  715.     GrafPtr gp;
  716.  
  717.     window_depth_cache_valid = 0;
  718.     GetPort(&gp);
  719.     fixup_colors();
  720.     SetPort(console.wp);
  721.     BeginUpdate(console.wp);
  722.     EraseRect(&console.wp->portRect);
  723.     draw_console();
  724.     if (!in_emacs_update) {
  725.         switch (cursor_state) {
  726.         case cursor_state_not_shown:    break;
  727.         case cursor_state_solid:        draw_cursor1(cursor_state_solid,1); break;
  728.         case cursor_state_outline:        draw_cursor1(cursor_state_outline,1); break;
  729.         }
  730.     }
  731.     my_DrawGrowIcon(console.wp);
  732.     EndUpdate(console.wp);
  733.     SetPort(gp);
  734. }
  735.  
  736. // These next two are never actually called, but the preprocessor #if's weren't
  737. // included around the calls.
  738. request_sigio() {}
  739. unrequest_sigio() {}
  740.  
  741. void
  742. console_change_fontsize(font,fontsize)
  743. {
  744.     Rect r;
  745.     GrafPtr gp;
  746.     long rows,cols;
  747.     
  748.     GetPort(&gp);
  749.     SetPort(console.wp);
  750.     set_console_font(font,fontsize);
  751.     windowsize2rowscols(&rows,&cols);
  752.     if (rows != console.rows || cols != console.cols) {
  753.         r = console.wp->portRect;
  754.         r.right -= 15;
  755.         EraseRect(&r);
  756.     
  757.         reset_size(rows,cols);
  758.  
  759.         // Tell Emacs
  760.         change_screen_size(console.rows,console.cols,0,0,0);
  761.     }
  762.     SetPort(gp);
  763. }
  764.  
  765. static void
  766. reset_window_preference(void)
  767. {
  768.     int left,top;
  769.     Rect **rh = (Rect **)NewHandle(sizeof(Rect));
  770.     
  771.     if (!MemError()) {
  772.         **rh = console.wp->portRect;
  773.         if (have_CQD) {
  774.             left = -(**((CGrafPtr)console.wp)->portPixMap).bounds.left;
  775.             top = -(**((CGrafPtr)console.wp)->portPixMap).bounds.top;
  776.         }
  777.         else {
  778.             left = -console.wp->portBits.bounds.left;
  779.             top = -console.wp->portBits.bounds.top;
  780.         }
  781.  
  782.         OffsetRect(*rh,left,top);
  783.         set_preference('DATA',128,rh);
  784.     }
  785. }
  786.  
  787. void
  788. console_grow(EventRecord *e)
  789. {
  790.     GrafPtr gp;
  791.     long width,height,rows,cols;
  792.     long newsize;
  793.     Rect r,old_portRect,**rh;
  794.     
  795.     r = (**GetGrayRgn()).rgnBBox;
  796.     r.left = r.top = 80;
  797.     newsize = GrowWindow(console.wp,e->where,&r);
  798.     if (newsize == 0) return;
  799.     
  800.     width = LoWord(newsize);
  801.     height = HiWord(newsize);
  802.     if (width == console.wp->portRect.right && height == console.wp->portRect.bottom)
  803.         return;
  804.  
  805.     GetPort(&gp);
  806.     SetPort(console.wp);
  807.     r = console.wp->portRect;
  808.     r.left = r.right - 15;
  809.     InvalRect(&r);
  810.     old_portRect = console.wp->portRect;
  811.     SizeWindow(console.wp,width,height,0);
  812.     r = console.wp->portRect;
  813.     r.left = r.right - 15;
  814.     InvalRect(&r);
  815.     window_depth_cache_valid = 0;
  816.  
  817.     reset_window_preference();
  818.  
  819.     windowsize2rowscols(&rows,&cols);
  820.     if (rows == console.rows && cols == console.cols) return;
  821.  
  822.     r = old_portRect;
  823.     r.right -= 15;
  824.     EraseRect(&r);
  825.     r = console.wp->portRect;
  826.     r.right -= 15;
  827.     EraseRect(&r);
  828.  
  829.     reset_size(rows,cols);
  830.  
  831.     // Tell Emacs.  We quote the original source:
  832.     /* This is absolutely, amazingly gross.  However, without
  833.        it, emacs will core dump if the window gets too small.
  834.        And uwm is too brain-damaged to handle large minimum size
  835.        windows.  */
  836.     if (cols > 11 && rows > 4) {
  837.         /* Delay the change unless Emacs is waiting for input.  */
  838.         extern int waiting_for_input;
  839.         // We'll always delay now.
  840.         change_screen_size(console.rows,console.cols,1 || !waiting_for_input,0,0);
  841.     }
  842.  
  843.     SetPort(gp);
  844. }
  845.  
  846. void
  847. console_content(EventRecord *e)
  848. {
  849.     GrafPtr gp;
  850.     Lisp_Object action,x,y;
  851.  
  852.     if (FrontWindow() != console.wp)
  853.         SelectWindow(console.wp);
  854.     else {
  855.         // This will do until we better emulate X.
  856.         // Need to include an argument with this
  857.  
  858.         GetPort(&gp);
  859.         SetPort(console.wp);
  860.         GlobalToLocal(&e->where);
  861.         SetPort(gp);
  862.         action = Fintern_soft(build_string(
  863.             e->modifiers & shiftKey ? "x-mouse-set-mark" : "x-mouse-set-point"),Qnil);
  864.         if (NULL(action)) { SysBeep(3); return; }
  865.         extract_position(e->where.h,e->where.v,&x,&y);
  866.         XSET(x,Lisp_Int,x);
  867.         XSET(y,Lisp_Int,y);
  868.         action = Fcons(action,Fcons(Fcons(Qquote,Fcons(Fcons(x,Fcons(y,Qnil)),Qnil)),Qnil));
  869.         pass_up_lisp_command(action);
  870.     }
  871. }
  872.  
  873. void
  874. console_drag(EventRecord *e)
  875. {
  876.     Rect r = (**GetGrayRgn()).rgnBBox;
  877.     DragWindow(console.wp,e->where,&r);
  878.     window_depth_cache_valid = 0;
  879.     reset_window_preference();
  880. }
  881.  
  882. WindowPtr
  883. console_window(void)
  884. {
  885.     return console.wp;
  886. }
  887.  
  888. WCTabHandle
  889. console_WCTabHandle(void)
  890. {
  891.     return console.ctab5_color;
  892. }
  893.